import { DatabaseManager } from '../database/DatabaseManager.js';
import { RedisClient } from '../cache/index.js';
import { RepositoryFactory } from '../database/repositories/index.js';

interface HealthStatus {
  status: 'healthy' | 'unhealthy' | 'degraded';
  timestamp: Date;
  details: string;
  responseTime?: number;
}

interface SystemHealth {
  overall: HealthStatus;
  components: {
    database: HealthStatus;
    cache: HealthStatus;
    repositories: HealthStatus;
  };
  uptime: number;
  version: string;
}

/**
 * 系统健康检查器
 */
export class HealthChecker {
  private static instance: HealthChecker;
  private startTime: Date;
  private dbManager?: DatabaseManager;
  private repositories?: RepositoryFactory;
  private lastCheck?: SystemHealth;
  private checkInterval = 60000; // 1分钟
  private checkTimer?: NodeJS.Timeout;

  constructor(dbManager?: DatabaseManager, repositories?: RepositoryFactory) {
    this.startTime = new Date();
    this.dbManager = dbManager;
    this.repositories = repositories;
    this.startPeriodicCheck();
  }

  /**
   * 获取单例实例
   */
  static getInstance(
    dbManager?: DatabaseManager, 
    repositories?: RepositoryFactory
  ): HealthChecker {
    if (!HealthChecker.instance) {
      HealthChecker.instance = new HealthChecker(dbManager, repositories);
    }
    return HealthChecker.instance;
  }

  /**
   * 执行完整的健康检查
   */
  async checkHealth(): Promise<SystemHealth> {
    const checkStart = Date.now();
    
    try {
      const [dbHealth, cacheHealth, repoHealth] = await Promise.all([
        this.checkDatabase(),
        this.checkCache(),
        this.checkRepositories(),
      ]);

      const overallStatus = this.determineOverallStatus([
        dbHealth,
        cacheHealth,
        repoHealth,
      ]);

      const health: SystemHealth = {
        overall: {
          status: overallStatus,
          timestamp: new Date(),
          details: this.getOverallDetails(overallStatus, [dbHealth, cacheHealth, repoHealth]),
          responseTime: Date.now() - checkStart,
        },
        components: {
          database: dbHealth,
          cache: cacheHealth,
          repositories: repoHealth,
        },
        uptime: Date.now() - this.startTime.getTime(),
        version: '1.0.0',
      };

      this.lastCheck = health;
      this.logHealthStatus(health);
      
      return health;
    } catch (error) {
      const errorHealth: SystemHealth = {
        overall: {
          status: 'unhealthy',
          timestamp: new Date(),
          details: `Health check failed: ${error instanceof Error ? error.message : String(error)}`,
          responseTime: Date.now() - checkStart,
        },
        components: {
          database: { status: 'unhealthy', timestamp: new Date(), details: 'Check failed' },
          cache: { status: 'unhealthy', timestamp: new Date(), details: 'Check failed' },
          repositories: { status: 'unhealthy', timestamp: new Date(), details: 'Check failed' },
        },
        uptime: Date.now() - this.startTime.getTime(),
        version: '1.0.0',
      };

      this.lastCheck = errorHealth;
      return errorHealth;
    }
  }

  /**
   * 检查数据库健康状态
   */
  private async checkDatabase(): Promise<HealthStatus> {
    if (!this.dbManager) {
      return {
        status: 'degraded',
        timestamp: new Date(),
        details: 'Database manager not initialized (running in memory mode)',
      };
    }

    try {
      const startTime = Date.now();
      const health = await this.dbManager.healthCheck();
      const responseTime = Date.now() - startTime;

      if (health.database.status === 'healthy') {
        return {
          status: 'healthy',
          timestamp: new Date(),
          details: `Database connection healthy (${health.database.details.database})`,
          responseTime,
        };
      } else {
        return {
          status: 'unhealthy',
          timestamp: new Date(),
          details: `Database connection failed: ${health.database.details.error}`,
          responseTime,
        };
      }
    } catch (error) {
      return {
        status: 'unhealthy',
        timestamp: new Date(),
        details: `Database check failed: ${error instanceof Error ? error.message : String(error)}`,
      };
    }
  }

  /**
   * 检查缓存健康状态
   */
  private async checkCache(): Promise<HealthStatus> {
    try {
      const startTime = Date.now();
      const health = await RedisClient.healthCheck();
      const responseTime = Date.now() - startTime;

      if (health.status === 'healthy') {
        return {
          status: 'healthy',
          timestamp: new Date(),
          details: `Redis cache healthy (${health.details.host}:${health.details.port})`,
          responseTime,
        };
      } else {
        return {
          status: 'degraded',
          timestamp: new Date(),
          details: `Redis cache unhealthy: ${health.details.error}`,
          responseTime,
        };
      }
    } catch (error) {
      return {
        status: 'degraded',
        timestamp: new Date(),
        details: `Cache check failed: ${error instanceof Error ? error.message : String(error)}`,
      };
    }
  }

  /**
   * 检查数据仓库健康状态
   */
  private async checkRepositories(): Promise<HealthStatus> {
    if (!this.repositories) {
      return {
        status: 'degraded',
        timestamp: new Date(),
        details: 'Repositories not initialized (running in memory mode)',
      };
    }

    try {
      const startTime = Date.now();
      const health = await this.repositories.checkHealth();
      const responseTime = Date.now() - startTime;

      if (health.status === 'healthy') {
        return {
          status: 'healthy',
          timestamp: new Date(),
          details: 'All repositories healthy',
          responseTime,
        };
      } else {
        return {
          status: 'unhealthy',
          timestamp: new Date(),
          details: 'Some repositories are unhealthy',
          responseTime,
        };
      }
    } catch (error) {
      return {
        status: 'unhealthy',
        timestamp: new Date(),
        details: `Repository check failed: ${error instanceof Error ? error.message : String(error)}`,
      };
    }
  }

  /**
   * 确定整体健康状态
   */
  private determineOverallStatus(componentStatuses: HealthStatus[]): 'healthy' | 'unhealthy' | 'degraded' {
    const hasUnhealthy = componentStatuses.some(s => s.status === 'unhealthy');
    const hasDegraded = componentStatuses.some(s => s.status === 'degraded');

    if (hasUnhealthy) {
      return 'unhealthy';
    } else if (hasDegraded) {
      return 'degraded';
    } else {
      return 'healthy';
    }
  }

  /**
   * 获取整体状态详情
   */
  private getOverallDetails(
    status: 'healthy' | 'unhealthy' | 'degraded',
    componentStatuses: HealthStatus[]
  ): string {
    const healthy = componentStatuses.filter(s => s.status === 'healthy').length;
    const total = componentStatuses.length;

    switch (status) {
      case 'healthy':
        return `All systems operational (${healthy}/${total} components healthy)`;
      case 'degraded':
        return `Some components are degraded (${healthy}/${total} components healthy)`;
      case 'unhealthy':
        return `System experiencing issues (${healthy}/${total} components healthy)`;
      default:
        return 'Unknown status';
    }
  }

  /**
   * 记录健康状态日志
   */
  private logHealthStatus(health: SystemHealth): void {
    const statusEmoji = {
      healthy: '✅',
      degraded: '⚠️',
      unhealthy: '❌',
    };

    const emoji = statusEmoji[health.overall.status];
    console.log(`${emoji} System Health: ${health.overall.status.toUpperCase()} (${health.overall.responseTime}ms)`);

    // 如果状态不健康，记录详细信息
    if (health.overall.status !== 'healthy') {
      console.warn(`📊 Health Details: ${health.overall.details}`);
      
      Object.entries(health.components).forEach(([name, component]) => {
        if (component.status !== 'healthy') {
          console.warn(`  - ${name}: ${component.status} - ${component.details}`);
        }
      });
    }
  }

  /**
   * 开始定期健康检查
   */
  private startPeriodicCheck(): void {
    this.checkTimer = setInterval(() => {
      this.checkHealth().catch(error => {
        console.error('❌ Periodic health check failed:', error);
      });
    }, this.checkInterval);

    // 立即执行一次检查
    this.checkHealth().catch(error => {
      console.error('❌ Initial health check failed:', error);
    });
  }

  /**
   * 获取最近的健康检查结果
   */
  getLastHealth(): SystemHealth | null {
    return this.lastCheck || null;
  }

  /**
   * 获取系统运行时间
   */
  getUptime(): number {
    return Date.now() - this.startTime.getTime();
  }

  /**
   * 获取格式化的运行时间
   */
  getFormattedUptime(): string {
    const uptimeMs = this.getUptime();
    const days = Math.floor(uptimeMs / (24 * 60 * 60 * 1000));
    const hours = Math.floor((uptimeMs % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
    const minutes = Math.floor((uptimeMs % (60 * 60 * 1000)) / (60 * 1000));
    const seconds = Math.floor((uptimeMs % (60 * 1000)) / 1000);

    const parts = [];
    if (days > 0) parts.push(`${days}天`);
    if (hours > 0) parts.push(`${hours}小时`);
    if (minutes > 0) parts.push(`${minutes}分钟`);
    if (seconds > 0) parts.push(`${seconds}秒`);

    return parts.join(' ') || '0秒';
  }

  /**
   * 生成健康报告
   */
  generateHealthReport(): string {
    const health = this.lastCheck;
    if (!health) {
      return '❌ 暂无健康检查数据';
    }

    const statusEmoji = {
      healthy: '✅',
      degraded: '⚠️',
      unhealthy: '❌',
    };

    return `
🏥 系统健康报告
==================

📊 整体状态: ${statusEmoji[health.overall.status]} ${health.overall.status.toUpperCase()}
📝 详细信息: ${health.overall.details}
⏱️  响应时间: ${health.overall.responseTime}ms
🚀 运行时间: ${this.getFormattedUptime()}

🔧 组件状态:
  • 数据库: ${statusEmoji[health.components.database.status]} ${health.components.database.details}
  • 缓存: ${statusEmoji[health.components.cache.status]} ${health.components.cache.details}
  • 数据仓库: ${statusEmoji[health.components.repositories.status]} ${health.components.repositories.details}

📅 检查时间: ${health.overall.timestamp.toISOString()}
🔖 系统版本: ${health.version}
    `.trim();
  }

  /**
   * 清理资源
   */
  cleanup(): void {
    if (this.checkTimer) {
      clearInterval(this.checkTimer);
      this.checkTimer = undefined;
    }
  }
}